package custom.base.utils;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;

import androidx.core.content.FileProvider;

import com.hjq.toast.ToastUtils;

import custom.base.data.MIME;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;


public class FileUtils implements MIME {


    private FileUtils() {
        super();
    }

    /**
     * 删除文件夹
     *
     * @param deleteThisPath 把本文件夹也删除掉
     */
    public static void deleteDir(String filePath, boolean deleteThisPath) {
        if (!TextUtils.isEmpty(filePath)) {
            File file = new File(filePath);

            if (file.isDirectory()) {// 处理目录
                File files[] = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    deleteDir(files[i].getAbsolutePath(), false);
                }
            }
            if (!file.isDirectory()) {// 如果是文件，删除
                file.delete();
            } else {// 目录,不删除
                if (deleteThisPath) {
                    if (file.listFiles().length == 0) {// 目录下没有文件或者目录，删除
                        file.delete();
                    }
                }

            }
        }
    }

    /**
     * 删除文件
     */
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param filePath 文件的路径
     */
    public static boolean isFileExists(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    public static String getAutoFileOrFilesSize(String filePath) {
        File file = new File(filePath);
        long blockSize = 0;
        try {
            if (file.isDirectory()) {
                blockSize = getDirSize(file.getAbsolutePath());
            } else {
                blockSize = getFileSize(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return formatFileSize(blockSize);
    }


    /**
     * get file size
     * <ul>
     * <li>if path is null or empty, return 0</li>
     * <li>if path exist and it is a file, return file size, else return 0</li>
     * <ul>
     *
     * @return returns the length of this file in bytes. returns -1 if the file does not exist.
     */
    public static long getFileSize(File file) {
        if (TextUtils.isEmpty(file.getAbsolutePath())) {
            return 0;
        }
        return (file.exists() && file.isFile() ? file.length() : -1);
    }

    /**
     * get file size
     * <ul>
     * <li>if path is null or empty, return 0</li>
     * <li>if path exist and it is a file, return file size, else return 0</li>
     * <ul>
     *
     * @return returns the length of this file in bytes. returns -1 if the file does not exist.
     */
    public static long getFileSize(String path) {
        if (TextUtils.isEmpty(path)) {
            return 0;
        }
        File file = new File(path);
        return (file.exists() && file.isFile() ? file.length() : -1);
    }

    /**
     * 获取指定文件夹大小
     *
     * @param path
     * @return
     * @throws Exception
     */
    public static long getDirSize(String path) throws Exception {
        File f = new File(path);
        long size = 0;
        File flist[] = f.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getDirSize(flist[i].getAbsolutePath());
            } else {
                size = size + getFileSize(flist[i]);
            }
        }
        return size;
    }

    /**
     * 获取文件个数 **
     */
    public static long getFileNums(File f) {// 递归求取目录文件个数
        long size = 0;
        File flist[] = f.listFiles();
        size = flist.length;
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileNums(flist[i]);
                size--;
            }
        }
        return size;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String formatFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String formatFileSize(String fileS) {
        long size = 0;
        try {
            size = Long.parseLong(fileS);
        } catch (Exception e) {

        }
        return formatFileSize(size);
    }


    /**
     * 小转换，之转换到MB
     */
    public static String formatFileSize2(long filesize) {
        String strUnit = "Bytes";
        String strAfterComma = "";
        int intDivisor = 1;
        if (filesize >= 1024 * 1024) {
            strUnit = "MB";
            intDivisor = 1024 * 1024;
        } else if (filesize >= 1024) {
            strUnit = "KB";
            intDivisor = 1024;
        }
        if (intDivisor == 1)
            return filesize + " " + strUnit;
        strAfterComma = "" + 100 * (filesize % intDivisor) / intDivisor;
        if (strAfterComma == "")
            strAfterComma = ".0";
        return filesize / intDivisor + "." + strAfterComma + " " + strUnit;
    }

    /**
     * 打开apk文件
     */
    public static void installAPKFile(File file, Context context) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);

        //大于7.0则用 contentUri
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(context, "com.xsdr.monitor.platform.fileprovider", file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            /* intent 设置数据和类型 */
            intent.setDataAndType(Uri.fromFile(file),
                    "application/vnd.android.package-archive");
        }

        context.startActivity(intent);

    }

    /**
     * 获取apk包的信息：版本号
     *
     * @param absPath apk包的绝对路径
     * @param context
     */
    public static String getApkFileVersion(Context context, String absPath) {
        if (new File(absPath).exists()) {
            PackageManager pm = context.getPackageManager();
            PackageInfo pkgInfo = pm.getPackageArchiveInfo(absPath,
                    PackageManager.GET_ACTIVITIES);
            if (pkgInfo != null) {
                ApplicationInfo appInfo = pkgInfo.applicationInfo;
                /* 必须加这两句，不然下面icon获取是default icon而不是应用包的icon */
                appInfo.sourceDir = absPath;
                appInfo.publicSourceDir = absPath;
                // String appName =
                // pm.getApplicationLabel(appInfo).toString();//
                // 得到应用名
                // String packageName = appInfo.packageName; // 得到包名
                String version = pkgInfo.versionName; // 得到版本信息
                return version;
            }
        }
        return null;
    }


    public static File createTmpFile(Context context) {

        String state = Environment.getExternalStorageState();
        if (state.equals(Environment.MEDIA_MOUNTED)) {
            // 已挂载
            File pic = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
            String fileName = "multi_image_" + timeStamp + "";
            File tmpFile = new File(pic, fileName + ".jpg");
            return tmpFile;
        } else {
            File cacheDir = context.getCacheDir();
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
            String fileName = "multi_image_" + timeStamp + "";
            File tmpFile = new File(cacheDir, fileName + ".jpg");
            return tmpFile;
        }

    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String FormetFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    /**
     * 打开文件
     *
     * @param file
     */
    public static void openFile(Context context, File file) {
        try {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //设置intent的Action属性
            intent.setAction(Intent.ACTION_VIEW);
            //获取文件file的MIME类型
            String type = getMIMEType(file);

            //大于7.0则用 contentUri
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(context, "com.xsdr.monitor.platform.fileprovider", file);
                intent.setDataAndType(contentUri, type);
            } else {
                //设置intent的data和Type属性。
                intent.setDataAndType(Uri.fromFile(file), type);
            }

            //跳转
            context.startActivity(intent); //这里最好try一下，有可能会报错。 //比如说你的MIME类型是打开邮箱，但是你手机里面没装邮箱客户端，就会报错。
        } catch (Exception e) {
            ToastUtils.show("未找到可以打开此文件的第三方软件");
        }
    }

    /**
     * 根据文件后缀名获得对应的MIME类型。
     *
     * @param file
     */
    private static String getMIMEType(File file) {

        String type = "*/*";
        String fName = file.getName();
        //获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if (dotIndex < 0) {
            return type;
        }
        /* 获取文件的后缀名*/
        String end = fName.substring(dotIndex, fName.length()).toLowerCase();
        if (end == "") return type;
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (int i = 0; i < MIME_MapTable.length; i++) { //MIME_MapTable??在这里你一定有疑问，这个MIME_MapTable是什么？
            if (end.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }

    /**
     * 得到文件名的后缀
     */
    public static String getSuffix(String nameOrPath) {
        if (nameOrPath == null)
            return "";
        return nameOrPath.substring(nameOrPath.lastIndexOf(".") + 1, nameOrPath.length());
    }

    /**
     * 得到文件名
     */
    public static String getFileNameByPath(String path) {
        if (path == null)
            return "";
        return path.substring(path.lastIndexOf("/") + 1, path.length());
    }

    /**
     * 得到文件名，不带后缀
     */
    public static String getFileNameWithoutSuffix(String pathOrName) {
        if (pathOrName == null)
            return "";
        if (pathOrName.lastIndexOf(".") > 0) {
            return pathOrName.substring(0, pathOrName.lastIndexOf("."));
        } else {
            return pathOrName;
        }
    }

    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径 如：c:/fqf.txt
     * @param newPath String 复制后路径 如：f:/fqf.txt
     * @return boolean
     */
    public static void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                int length;
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字节数 文件大小
                    System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();
        }
    }

    /**
     * 复制整个文件夹内容
     *
     * @param oldPath String 原文件路径 如：c:/fqf
     * @param newPath String 复制后路径 如：f:/fqf/ff
     * @return boolean
     */
    public static void copyFolder(String oldPath, String newPath) {

        try {
            (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹
            File a = new File(oldPath);
            String[] file = a.list();
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file[i]);
                } else {
                    temp = new File(oldPath + File.separator + file[i]);
                }

                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = new FileOutputStream(newPath + "/" +
                            (temp.getName()).toString());
                    byte[] b = new byte[1024 * 5];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                if (temp.isDirectory()) {//如果是子文件夹
                    copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
                }
            }
        } catch (Exception e) {
            System.out.println("复制整个文件夹内容操作出错");
            e.printStackTrace();
        }
    }


    /**
     * 通知媒体库更新文件
     *
     * @param context
     * @param filePath 文件全路径
     */
    public static void scanFile(Context context, String filePath) {
        Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        scanIntent.setData(Uri.fromFile(new File(filePath)));
        context.sendBroadcast(scanIntent);
    }
//
//    /**
//     * 得到不重复的名字，如果名字重复会在名称后加1/2/3 以此类推知道不重复为止
//     */
//    public static String getIndependentFileName(String path) {
//        try {
//            File file = new File(path);
//            if (file.exists()) {
//                String p = file.getAbsolutePath();
//                String withOutSuffix = p.substring(0, p.lastIndexOf("."));
//                String suffix = getSuffix(p);
//                String lastChar = withOutSuffix.substring(withOutSuffix.length() - 1, withOutSuffix.length());
//                lastChar = (TxtUtil.getInteger(lastChar) + 1) + "";
//                return getIndependentFileName(withOutSuffix + lastChar + "." + suffix);
//            } else {
//                return path;
//            }
//        } catch (Exception e) {
//            return path;
//        }
//    }

    private static List<String> suffixList = new ArrayList<>();

    public static List<String> initSuffixList() {
        if (suffixList == null)
            suffixList = new ArrayList<>();

        if (suffixList.size() == 0) {
            suffixList.add(".doc");
            suffixList.add(".docx");
            suffixList.add(".xls");
            suffixList.add(".xlsx");
            suffixList.add(".pdf");
            suffixList.add(".ppt");
            suffixList.add(".pptx");
            suffixList.add(".png");
            suffixList.add(".jpg");
            suffixList.add(".jpeg");
            suffixList.add(".bmp");
            suffixList.add(".tif");
            suffixList.add(".gif");
            suffixList.add(".rm");
            suffixList.add(".rmvb");
            suffixList.add(".wmv");
            suffixList.add(".avi");
            suffixList.add(".mp4");
            suffixList.add(".3gp");
            suffixList.add(".mkv");
            suffixList.add(".rar");
            suffixList.add(".r");
            suffixList.add(".zip");
            suffixList.add(".z");
            suffixList.add(".cab");
            suffixList.add(".arj");
            suffixList.add(".lzh");
            suffixList.add(".ace");
            suffixList.add(".7-zip");
            suffixList.add(".tar");
            suffixList.add(".gzip");
            suffixList.add(".uue");
            suffixList.add(".bz2");
            suffixList.add(".jar");
            suffixList.add(".iso");
            suffixList.add(".apk");

            List<String> list = new ArrayList<>();
            for (int i = 0; i < suffixList.size(); i++) {//添加所有大写后缀
                list.add(suffixList.get(i).toUpperCase());
            }

            suffixList.addAll(list);
        }
        return suffixList;
    }

    /**
     * 判断该字符串是否含有后缀
     */
    public static boolean haveSuffix(String fileOrUrl) {
        if (fileOrUrl == null)
            return false;
        initSuffixList();//装载后缀列表
        for (int i = 0; i < suffixList.size(); i++) {
            if (fileOrUrl.endsWith(suffixList.get(i))) {
                return true;
            }
        }
        return false;
    }


    private static ArrayList<File> scanFiles = new ArrayList<>();

    /**
     * TODO:递归扫描指定文件夹下面的指定文件
     *
     * @param ignores 忽略的文件或文件夹
     * @return ArrayList<Object>
     * @throws FileNotFoundException
     */
    public static void scanFiles(String folderPath, onScanFilesListener listener, String... ignores) throws FileNotFoundException {
        File directory = new File(folderPath);
        if (!directory.isDirectory()) {
            throw new FileNotFoundException('"' + folderPath + '"' + " input path is not a Directory , please input the right path of the Directory. ^_^...^_^");
        }
        File[] filelist = directory.listFiles();
        for (int i = 0; i < filelist.length; i++) {
            boolean jump = false;//判断是否是忽略的文件
            if (ignores != null)
                for (int j = 0; j < ignores.length; j++) {
                    if (ignores[j].equals(filelist[i].getName())) {//是忽略文件
                        jump = true;
                        break;
                    }
                }
            if (jump) {
                continue;
            }

            /**如果当前是文件夹，进入递归扫描文件夹**/
            if (filelist[i].isDirectory()) {
                /**递归扫描下面的文件夹**/
                scanFiles(filelist[i].getAbsolutePath(), listener, ignores);
            }
            /**非文件夹**/
            else {
                scanFiles.add(filelist[i]);
                if (listener != null) {
                    listener.onScan(filelist[i], scanFiles);
                }
//                    System.out.println(filelist[i].getAbsolutePath());
            }
        }
    }


    public interface onScanFilesListener {
        /**
         * @param file      当前扫描出的文件
         * @param scanFiles 总共扫描出的文件
         */
        void onScan(File file, ArrayList<File> scanFiles);
    }


    /**
     * 第二种
     * 追加文件：使用FileWriter
     *
     * @param fileName
     * @param content
     */
    public static void writeFile(String fileName, String content) {
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            FileWriter writer = new FileWriter(fileName, true);
            writer.write(content);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
